package com.tanhua.dubbo.server.api;

import com.alibaba.dubbo.config.annotation.Service;
import com.mongodb.client.result.DeleteResult;
import com.tanhua.dubbo.server.pojo.*;
import com.tanhua.dubbo.server.service.IdService;
import com.tanhua.dubbo.server.vo.PageInfo;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

@Service(version = "1.0.0")
public class QuanZiApiImpl implements QuanZiApi {


    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IdService idService;


    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String CACHE_KEY_FREEZE_PREFIX = "FREEZE_KEY_";

    /**
     * 发布动态
     *
     * @param publish
     * @return
     */
    @Override
    public String savePublish(Publish publish) {

        //判断publish的id是否为空
        if (publish.getUserId() == null) {
            return null;
        }

        try {
            //发布动态
            publish.setCreated(System.currentTimeMillis());   //设置系统时间
            publish.setId(ObjectId.get());  //设置id
            publish.setSeeType(1);  //查看权限

            publish.setPid(idService.createId("publish", publish.getId().toHexString()));
            this.mongoTemplate.save(publish);  //保存发布


            //创建相册对象
            Album album = new Album();
            album.setPublishId(publish.getId());
            album.setCreated(System.currentTimeMillis());
            album.setId(ObjectId.get());
            mongoTemplate.save(album, "quanzi_album_" + publish.getUserId());

            //写入好友的时间线中

            Criteria criteria = Criteria.where("userId").is(publish.getUserId());
            List<Users> users = this.mongoTemplate.find(Query.query(criteria), Users.class);
            for (Users user : users) {
                TimeLine timeLine = new TimeLine();
                timeLine.setId(ObjectId.get());
                timeLine.setPublishId(publish.getId());
                timeLine.setUserId(user.getUserId());
                timeLine.setDate(System.currentTimeMillis());
                mongoTemplate.save(timeLine, "quanzi_time_line_" + user.getFriendId());
            }

            return publish.getId().toHexString();
        } catch (Exception e) {
            e.printStackTrace();
            //TODO 出错的事务回滚
        }


        return null;
    }


    /**
     * 查询好友及推荐动态
     * 好友动态和推荐动态的区别是不需要传入用户id
     *
     * @param userId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Publish> queryPublishList(Long userId, Integer pageNum, Integer pageSize) {

        //构建条件根据发布时间倒叙排序
        PageRequest request = PageRequest.of(pageNum - 1, pageSize, Sort.by(Sort.Order.desc("date")));
        Query query = new Query().with(request);

        //创建表名字段
        String tableName = "quanzi_time_line_";
        //如果传入的userID为空 就查询推荐用户
        if (null == userId) {
            tableName += "recommend";
            //有userId就查询好友列表
        } else {
            tableName += userId;
        }
        //查询的是自己的时间线表
        List<TimeLine> timeLines = mongoTemplate.find(query, TimeLine.class, tableName);

        //获取好友发布动态的id
        List<ObjectId> publishs = new ArrayList<>();
        for (TimeLine timeLine : timeLines) {
            publishs.add(timeLine.getPublishId());
        }

        //查询发布的信息
        Query queryPublish = Query.query(Criteria.where("id").in(publishs)).with(Sort.by(Sort.Order.desc("created")));

        List<Publish> publishList = mongoTemplate.find(queryPublish, Publish.class);
        //创建PageInfo对象
        PageInfo<Publish> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(publishList);
        pageInfo.setTotal(0);  //不提供总数

        return pageInfo;
    }

    /**
     * 点赞
     *
     * @param userId    用户id
     * @param publishId 发布id
     * @return
     */
    @Override
    public Boolean saveLikeComment(Long userId, String publishId) {
        //判断是否已经点赞,如果已经点赞就返回
        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(1);
        Query query = Query.query(criteria);

        //调用count方法
        long count = mongoTemplate.count(query, Comment.class);
        //如果count大于0说明已经点过赞了
        if (count > 0) {
            return false;
        }
        //没点过.继续添加
        return saveComment(userId, publishId, 1, null);
    }

    /**
     * 取消点赞 喜欢
     *
     * @param userId      用户id
     * @param publishId   发布id
     * @param commentType //评论类型
     * @return
     */
    @Override
    public Boolean removeComment(Long userId, String publishId, Integer commentType) {
        //构建点赞的条件,找到mongodb中的数据,进行删除及可
        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(commentType);
        Query query = Query.query(criteria);

        DeleteResult remove = mongoTemplate.remove(query, Comment.class);

        return remove.getDeletedCount() > 0;
    }

    /**
     * 喜欢
     *
     * @param userId    用户id
     * @param publishId 发布id
     * @return
     */
    @Override
    public Boolean saveLoveComment(Long userId, String publishId) {
        //判断是否已经喜欢过了,如果点过喜欢了,就不能再点喜欢了
        //构建查询条件  因为comment这个类直接对应的是mongodb中的表,所以字段名是相同的
        Criteria criteria = Criteria.where("userId").is(userId)
                .and("publishId").is(new ObjectId(publishId))
                .and("commentType").is(3);

        //调用mongoTemplate获取count
        long count = mongoTemplate.count(Query.query(criteria), Comment.class);
        //如果count大于0 ,则不能再点击喜欢
        if (count > 0) {
            return false;
        }
        //不大于0,则继续点击添加
        return saveComment(userId, publishId, 3, null);
    }

    /**
     * 保存评论
     *
     * @param userId      用户id
     * @param publishId   发布id
     * @param commentType 评论类型
     * @param content     评论
     * @return
     */
    @Override
    public Boolean saveComment(Long userId, String publishId, Integer commentType, String content) {
        String reqSaveSpeak = redisTemplate.opsForValue().get(CACHE_KEY_FREEZE_PREFIX + userId.toString());
        if("2".equals(reqSaveSpeak)){
            return false;
        }
        try {
            Comment comment = new Comment();
            comment.setContent(content);   //评论
            comment.setIsParent(true);  //是否是父节点  默认是
            comment.setCommentType(commentType);  //评论类型   1.点赞  2.评论  3.喜欢
            comment.setPublishId(new ObjectId(publishId));  //发布id
            comment.setUserId(userId);   //用户id
            comment.setId(ObjectId.get());  //主键id
            comment.setCreated(System.currentTimeMillis());  //时间

            //根据publishId获取到pulish用户的id
            Publish publish = mongoTemplate.findById(comment.getPublishId(), Publish.class);

            //设置发布人的id    不是小视频的评论就是动态的评论
            if (null != publish) {
                comment.setPublishUserId(publish.getUserId());  //动态的用户id
            } else {
                Video video = mongoTemplate.findById(comment.getPublishId(), Video.class);
                if (null != video) {
                    comment.setPublishUserId(video.getUserId());
                }
            }
            //保存到mongodb中
            mongoTemplate.save(comment);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 查询评论数
     *
     * @param publishId   发布id
     * @param commentType 评论类型
     * @return
     */
    @Override
    public Long queryCommentCount(String publishId, Integer commentType) {

        //查询评论数 只需要根据发布的id和评论类型查询
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(publishId))
                .and("commentType").is(commentType));

        return mongoTemplate.count(query, Comment.class);
    }


    /**
     * 根据id查询单条动态
     *
     * @param publishId
     * @return
     */
    @Override
    public Publish queryPublishById(String publishId) {
        //根据id查询单条动态
        return this.mongoTemplate.findById(new ObjectId(publishId), Publish.class);

    }


    /**
     * 单条动态查询评论
     *
     * @param publishId 发布id
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Comment> queryCommentList(String publishId, Integer page, Integer pageSize) {

        //构建条件查询comment表中单条动态
        //分页条件,并按照发布的时间正序排序
        Pageable pageable = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.asc("created")));
        //Comment 对象中的publishId 为ObjectId 类型 需要转换
        Query query = Query.query(Criteria.where("publishId").is(new ObjectId(publishId)).and("commentType").is(2)).with(pageable);

        //查询评论表
        List<Comment> comments = mongoTemplate.find(query, Comment.class);
        //创建pageinfo对象
        PageInfo<Comment> pageInfo = new PageInfo<>();
        //封装参数
        pageInfo.setPageNum(page);  //页码
        pageInfo.setPageSize(pageSize); //条目数
        pageInfo.setRecords(comments);  //comment对象
        pageInfo.setTotal(0); //不提供总数
        return pageInfo;
    }

    /**
     * @param userId
     * @param type     评论类型
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Comment> queryCommentListByUser(Long userId, Integer type, Integer page, Integer pageSize) {
        //时间倒叙排序
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
        Query query = new Query(Criteria
                .where("publishUserId").is(userId)
                .and("commentType").is(type)).with(pageRequest);

        List<Comment> commentList = this.mongoTemplate.find(query, Comment.class);

        PageInfo<Comment> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setRecords(commentList);
        pageInfo.setTotal(0); //不提供总数
        return pageInfo;
    }


    /**
     * 根据pid批量查询数据
     *
     * @param pidList
     * @return
     */
    @Override
    public List<Publish> queryPublishByPids(List<Long> pidList) {

        Query query = Query.query(Criteria.where("pid").in(pidList));
        return mongoTemplate.find(query, Publish.class);

    }

    /**
     * 查询自己的相册表
     *
     * @param userId   当前用户的id
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<Publish> queryAlbumList(Long userId, Integer page, Integer pageSize) {
        //创建pageInfo集合封装Publish
        PageInfo<Publish> pageInfo = new PageInfo<>();
        //封装基本数据
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotal(0); //不提供总数

        //构建mongodb查询条件
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));

        Query query = new Query().with(pageRequest);

        List<Album> albumList = mongoTemplate.find(query, Album.class, "quanzi_album_" + userId);

        //查询结果为空
        if (CollectionUtils.isEmpty(albumList)) {
            return pageInfo;
        }

        List<Object> publishIds = new ArrayList<>();
        for (Album album : albumList) {
            publishIds.add(album.getPublishId());
        }

        //查询发布的动态信息

        Query  queryPublish = query.query(Criteria.where("id").in(publishIds))
                .with(Sort.by(Sort.Order.desc("created")));

        List<Publish> publishList = mongoTemplate.find(queryPublish, Publish.class);
        pageInfo.setRecords(publishList);
        return pageInfo;
    }
}
